home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tar.gnu / sprite / create.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-29  |  32.7 KB  |  1,388 lines

  1. /* Create a tar archive.
  2.    Copyright (C) 1988 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Create a tar archive.
  22.  *
  23.  * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  24.  *
  25.  * @(#)create.c 1.36 11/6/87 - gnu
  26.  *
  27.  * $Header: /sprite/src/cmds/tar.gnu/sprite/RCS/create.c,v 1.5 92/03/28 17:31:24 kupfer Exp $ SPRITE (Berkeley)
  28.  */
  29. #include <sys/types.h>
  30. #include <sys/stat.h>
  31. #include <sys/file.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <sys/param.h>
  35. #include <assert.h>
  36.  
  37. /* JF: this one is my fault */
  38. /* #include "utils.h" */
  39.  
  40. #ifndef V7
  41. #include <fcntl.h>
  42. #endif
  43.  
  44. #ifndef    MSDOS
  45. #include <pwd.h>
  46. #include <grp.h>
  47. #endif
  48.  
  49. #ifdef BSD42
  50. #include <sys/dir.h>
  51. #else
  52. #ifdef MSDOS
  53. #include <sys/dir.h>
  54. #else
  55. #ifdef USG
  56. #include "dirent.h"
  57. #define direct dirent
  58. #define DP_NAMELEN(x) strlen((x)->d_name)
  59. #else
  60. /*
  61.  * FIXME: On other systems there is no standard place for the header file
  62.  * for the portable directory access routines.  Change the #include line
  63.  * below to bring it in from wherever it is.
  64.  */
  65. #include "ndir.h"
  66. #endif
  67. #endif
  68. #endif
  69.  
  70. #ifndef DP_NAMELEN
  71. #define DP_NAMELEN(x)    (x)->d_namlen
  72. #endif
  73.  
  74. #ifdef USG
  75. #include <sys/sysmacros.h>    /* major() and minor() defined here */
  76. #endif
  77.  
  78. /*
  79.  * V7 doesn't have a #define for this.
  80.  */
  81. #ifndef O_RDONLY
  82. #define    O_RDONLY    0
  83. #endif
  84.  
  85. /*
  86.  * Most people don't have a #define for this.
  87.  */
  88. #ifndef    O_BINARY
  89. #define    O_BINARY    0
  90. #endif
  91.  
  92. #include "tar.h"
  93. #include "port.h"
  94.  
  95. extern union record *head;        /* Points to current tape header */
  96. extern struct stat hstat;        /* Stat struct corresponding */
  97. extern int head_standard;        /* Tape header is in ANSI format */
  98.  
  99. /* JF */
  100. extern struct name *gnu_list_name;
  101.  
  102. /*
  103.  * If there are no symbolic links, there is no lstat().  Use stat().
  104.  */
  105. #ifndef S_IFLNK
  106. #define lstat stat
  107. #endif
  108.  
  109. extern char    *malloc();
  110. extern char    *strcpy();
  111. extern char    *strncpy();
  112. extern void    bzero();
  113. extern void    bcopy();
  114. extern int    errno;
  115.  
  116. extern void print_header();
  117.  
  118. union record *start_header();
  119. void finish_header();
  120. void finduname();
  121. void findgname();
  122. char *name_next();
  123. void to_oct();
  124. void dump_file();
  125.  
  126. static nolinks;            /* Gets set if we run out of RAM */
  127.  
  128. #ifdef __STDC__
  129. static int copy_long_name(char *name, int type);
  130. #else
  131. static int copy_long_name();
  132. #endif
  133.  
  134. static char longname[MAXPATHLEN+1];
  135.  
  136. /*
  137.  * "Scratch" space to store the information about a sparse file before
  138.  * writing the info into the header or extended header
  139.  */
  140. /* struct sp_array     *sparsearray;*/
  141.  
  142. /* number of elts storable in the sparsearray */
  143. /*int     sparse_array_size = 10;*/
  144.  
  145. void
  146. create_archive()
  147. {
  148.     register char    *p;
  149.     char *name_from_list();
  150.  
  151.     open_archive(0);        /* Open for writing */
  152.  
  153.     if(f_gnudump) {
  154.         char buf[MAXNAMLEN],*q,*bufp;
  155.  
  156.         collect_and_sort_names();
  157.  
  158.         while(p=name_from_list())
  159.             dump_file(p,-1);
  160.         /* if(!f_dironly) { */
  161.             blank_name_list();
  162.             while(p=name_from_list()) {
  163.                 strcpy(buf,p);
  164.                 if(p[strlen(p)-1]!='/')
  165.                     strcat(buf,"/");
  166.                 bufp=buf+strlen(buf);
  167.                 for(q=gnu_list_name->dir_contents;*q;q+=strlen(q)+1) {
  168.                     if(*q=='Y') {
  169.                         strcpy(bufp,q+1);
  170.                         dump_file(buf,-1);
  171.                     }
  172.                 }
  173.             }
  174.         /* } */
  175.  
  176.     } else {
  177.         while (p = name_next(1)) {
  178.             dump_file(p, -1);
  179.         }
  180.     }
  181.  
  182.     write_eot();
  183.     close_archive();
  184.     name_close();
  185. }
  186.  
  187. /*
  188.  * Dump a single file.  If it's a directory, recurse.
  189.  * Result is 1 for success, 0 for failure.
  190.  * Sets global "hstat" to stat() output for this file.
  191.  */
  192. void
  193. dump_file (p, curdev)
  194.     char    *p;            /* File name to dump */
  195.     int    curdev;            /* Device our parent dir was on */
  196. {
  197.     union record    *header;
  198.     char type;
  199.     extern char *save_name;        /* JF for multi-volume support */
  200.     extern long save_totsize;
  201.     extern long save_sizeleft;
  202.     union record    *exhdr;
  203.     char save_linkflag;
  204.     extern time_t new_time;
  205.  
  206.  
  207.     if(f_confirm && !confirm("add",p))
  208.         return;
  209.  
  210.     /*
  211.      * Use stat if following (rather than dumping) 4.2BSD's
  212.      * symbolic links.  Otherwise, use lstat (which, on non-4.2
  213.      * systems, is #define'd to stat anyway.
  214.      */
  215.     if (0 != f_follow_links? stat(p, &hstat): lstat(p, &hstat))
  216.     {
  217. badperror:
  218.         msg_perror("can't add file %s",p);
  219. badfile:
  220.         errors++;
  221.         return;
  222.     }
  223.  
  224.     /* See if we only want new files, and check if this one is too old to
  225.        put in the archive. */
  226.     if(   f_new_files
  227.        && new_time>hstat.st_mtime
  228.        && (hstat.st_mode&S_IFMT)!=S_IFDIR
  229.        && (f_new_files>1 || new_time>hstat.st_ctime)) {
  230.         if(curdev<0) {
  231.             msg("%s: is unchanged; not dumped",p);
  232.         }
  233.         return;
  234.     }
  235.  
  236.     /*
  237.      * See if we are crossing from one file system to another,
  238.      * and avoid doing so if the user only wants to dump one file system.
  239.      */
  240.     if (f_local_filesys && curdev >= 0 && curdev != hstat.st_dev) {
  241.         msg("%s: is on a different filesystem; not dumped",p);
  242.         return;
  243.     }
  244.  
  245.     /*
  246.      * Check for multiple links.
  247.      *
  248.      * We maintain a list of all such files that we've written so
  249.      * far.  Any time we see another, we check the list and
  250.      * avoid dumping the data again if we've done it once already.
  251.      */
  252.     if (hstat.st_nlink > 1) switch (hstat.st_mode & S_IFMT) {
  253.         register struct link    *lp;
  254.  
  255.     case S_IFREG:            /* Regular file */
  256. #ifdef S_IFCTG
  257.     case S_IFCTG:            /* Contigous file */
  258. #endif
  259. #ifdef S_IFCHR
  260.     case S_IFCHR:            /* Character special file */
  261. #endif
  262.  
  263. #ifdef S_IFBLK
  264.     case S_IFBLK:            /* Block     special file */
  265. #endif
  266.  
  267. #ifdef S_IFIFO
  268.     case S_IFIFO:            /* Fifo      special file */
  269. #endif
  270.  
  271.         /* First quick and dirty.  Hashing, etc later FIXME */
  272.         for (lp = linklist; lp; lp = lp->next) {
  273.             if (lp->ino == hstat.st_ino &&
  274.                 lp->dev == hstat.st_dev) {
  275.                 char *link_name = lp->name;
  276.  
  277.                 /* We found a link. */
  278.                 hstat.st_size = 0;
  279.                 header = start_header(p, &hstat);
  280.                 if (header == NULL) goto badfile;
  281.                 while(!f_absolute_paths && *link_name == '/') {
  282.                     static int link_warn = 0;
  283.  
  284.                     if (!link_warn) {
  285.                         msg("Removing leading / from absolute links");
  286.                         link_warn++;
  287.                     }
  288.                     link_name++;
  289.                 }
  290.                 header->header.linkflag = LF_LINK;
  291.                 /* 
  292.                  * BSD tar requires that the link name have 
  293.                  * a trailing null.  See the comments in 
  294.                  * start_header.
  295.                  */
  296.                 if (strlen(link_name) < NAMSIZ) {
  297.                     strcpy(header->header.linkname,
  298.                            link_name);
  299.                     finish_header(header);
  300.                 } else if (!f_long_names) {
  301.                     msg("link name ``%s'' too long.",
  302.                         link_name);
  303.                     return;
  304.                 } else {
  305.                     header->header.isextended |= XH_LINKNAME;
  306.                     strcpy(header->header.linkname,
  307.                            "LINK_TOO_LONG--CHECK_EXTENDED_HEADER");
  308.                     finish_header(header);
  309.                     copy_long_name(link_name, XH_LINKNAME);
  310.                 }
  311.         /* FIXME: Maybe remove from list after all links found? */
  312.                 return;        /* We dumped it */
  313.             }
  314.         }
  315.  
  316.         /* Not found.  Add it to the list of possible links. */
  317.         lp = (struct link *) malloc( (unsigned)
  318.             (strlen(p) + sizeof(struct link) - NAMSIZ));
  319.         if (!lp) {
  320.             if (!nolinks) {
  321.                 fprintf(stderr,
  322.     "tar: no memory for links, they will be dumped as separate files\n");
  323.                 nolinks++;
  324.             }
  325.         }
  326.         lp->ino = hstat.st_ino;
  327.         lp->dev = hstat.st_dev;
  328.         strcpy(lp->name, p);
  329.         lp->next = linklist;
  330.         linklist = lp;
  331.     }
  332.  
  333.     /*
  334.      * This is not a link to a previously dumped file, so dump it.
  335.      */
  336.     switch (hstat.st_mode & S_IFMT) {
  337.  
  338.     case S_IFREG:            /* Regular file */
  339. #ifdef S_IFCTG
  340.     case S_IFCTG:            /* Contiguous file */
  341. #endif
  342.     {
  343.         int    f;        /* File descriptor */
  344.         long    bufsize, count;
  345.         long    sizeleft;
  346.         register union record     *start;
  347.         int     header_moved;
  348.         char    isextended = 0;
  349.         int     upperbound;
  350.         int    end_nulls = 0;
  351.  
  352.         header_moved = 0;
  353.  
  354. #ifdef BSD42
  355.         if (f_sparse_files) {
  356.         /*
  357.          * JK - This is the test for sparseness: whether the
  358.          * "size" of the file matches the number of blocks
  359.          * allocated for it.  If there is a smaller number
  360.          * of blocks that would be necessary to accommodate
  361.          * a file of this size, we have a sparse file, i.e.,
  362.          * at least one of those records in the file is just
  363.          * a useless hole.
  364.          */
  365.             if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE) {
  366.                 int    filesize = hstat.st_size;
  367.                 register int i;
  368.                 
  369.                 printf("File is sparse: %s\n", p);
  370.                 header = start_header(p, &hstat);
  371.                 if (header == NULL)
  372.                     goto badfile;
  373.                 header->header.linkflag = LF_SPARSE;
  374.                 header_moved++;
  375.                 
  376.             /*
  377.              * Call the routine that figures out the
  378.              * layout of the sparse file in question.
  379.              * UPPERBOUND is the index of the last
  380.              * element of the "sparsearray," i.e.,
  381.              * the number of elements it needed to
  382.              * describe the file.
  383.              */
  384.  
  385.                 upperbound = deal_with_sparse(p, header);
  386.  
  387.             /* 
  388.              * See if we'll need an extended header
  389.              * later
  390.              */
  391.                     if (upperbound > SPARSE_IN_HDR-1)
  392.                     header->header.isextended |= XH_SPARSE_FILE;
  393.  
  394.             /*
  395.              * We store the "real" file size so
  396.              * we can show that in case someone wants
  397.              * to list the archive, i.e., tar tvf <file>.
  398.              * It might be kind of disconcerting if the
  399.              * shrunken file size was the one that showed
  400.              * up.
  401.              */
  402.                  to_oct((long) hstat.st_size, 1+12, 
  403.                         header->header.realsize);
  404.                     
  405.             /*
  406.              * This will be the new "size" of the
  407.              * file, i.e., the size of the file
  408.              * minus the records of holes that we're
  409.              * skipping over. 
  410.              */
  411.                  
  412.                 find_new_file_size(&filesize, upperbound);
  413.                 printf("File %s is now size %d\n", 
  414.                             p, filesize);
  415.                 hstat.st_size = filesize;
  416.                 to_oct((long) filesize, 1+12,
  417.                          header->header.size);
  418. /*                to_oct((long) end_nulls, 1+12, 
  419.                         header->header.ending_blanks);*/
  420.                         
  421.                 for (i = 0; i < SPARSE_IN_HDR; i++) {
  422.                     if (!sparsearray[i].numbytes)
  423.                         break;
  424.                     to_oct(sparsearray[i].offset, 1+12,
  425.                         header->header.sp[i].offset);
  426.                     to_oct(sparsearray[i].numbytes, 1+12,
  427.                         header->header.sp[i].numbytes);
  428.                 }
  429.                     
  430.             }
  431.         }
  432. #endif
  433.         
  434.         sizeleft = hstat.st_size;
  435.         /* Don't bother opening empty, world readable files. */
  436.         if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode)) {
  437.             f = open(p, O_RDONLY|O_BINARY);
  438.             if (f < 0) goto badperror;
  439.         } else {
  440.             f = -1;
  441.         }
  442.  
  443.         /* If the file is sparse, we've already taken care of this */
  444.         if (!header_moved) {
  445.             header = start_header(p, &hstat);
  446.             if (header == NULL) {
  447.                 if(f>=0)
  448.                     (void)close(f);
  449.                 goto badfile;
  450.             }
  451.         }
  452. #ifdef S_IFCTG
  453.         /* Mark contiguous files, if we support them */
  454.         if (f_standard && (hstat.st_mode & S_IFMT) == S_IFCTG) {
  455.             header->header.linkflag = LF_CONTIG;
  456.         }
  457. #endif
  458.         save_linkflag = header->header.linkflag;
  459.         finish_header(header);
  460.         if (isextended) {
  461.             int     sum = 0;
  462.             register int i;
  463. /*            register union record *exhdr;*/
  464.             static int index_offset = SPARSE_IN_HDR;
  465.  
  466.     extend:        exhdr = findrec();
  467.  
  468.             if (exhdr == NULL) goto badfile;
  469.             bzero(exhdr->charptr, RECORDSIZE);
  470.             exhdr->ext_hdr.xh_type = XH_SPARSE_FILE;
  471.             for (i = 0; i < SPARSE_EXT_HDR; i++) {
  472.                 if (i+index_offset > upperbound)
  473.                     break;
  474.                 to_oct((long) sparsearray[i+index_offset].numbytes,
  475.                     1+12,
  476.                     exhdr->ext_hdr.xh_sp[i].numbytes);
  477.                 to_oct((long) sparsearray[i+index_offset].offset,
  478.                     1+12,
  479.                     exhdr->ext_hdr.xh_sp[i].offset);
  480.             }
  481.             userec(exhdr);
  482. /*            sum += i;
  483.             if (sum < upperbound)
  484.                 goto extend;*/
  485.             if (index_offset+i < upperbound) {
  486.                 index_offset += i;
  487.                 exhdr->ext_hdr.xh_isextended |= XH_SPARSE_FILE;
  488.                 goto extend;
  489.             }
  490.  
  491.         }
  492.         if (save_linkflag == LF_SPARSE) {
  493.             if (finish_sparse_file(f, &sizeleft, hstat.st_size, p))
  494.                 goto padit;
  495.         }
  496.         else
  497.           while (sizeleft > 0) {
  498.  
  499.             if(f_multivol) {   
  500.                 save_name = p;
  501.                 save_sizeleft = sizeleft;
  502.                 save_totsize = hstat.st_size;
  503.             }
  504.             start = findrec();
  505.  
  506.             bufsize = endofrecs()->charptr - start->charptr;
  507.  
  508.             if (sizeleft < bufsize) {
  509.                 /* Last read -- zero out area beyond */
  510.                 bufsize = (int)sizeleft;
  511.                 count = bufsize % RECORDSIZE;
  512.                 if (count) 
  513.                     bzero(start->charptr + sizeleft,
  514.                         (int)(RECORDSIZE - count));
  515.             }
  516.             count = read(f, start->charptr, bufsize);
  517.             if (count < 0) {
  518.                 msg_perror("read error at byte %ld, reading\
  519.  %d bytes, in file %s",  hstat.st_size - sizeleft, bufsize,p);
  520.                 goto padit;
  521.             }
  522.             sizeleft -= count;
  523.  
  524.             /* This is nonportable (the type of userec's arg). */
  525.             userec(start+(count-1)/RECORDSIZE);
  526.  
  527.             if (count == bufsize) continue;
  528.             msg( "file %s shrunk by %d bytes, padding with zeros.\n", p, sizeleft);
  529.             goto padit;        /* Short read */
  530.         }
  531.  
  532.         if(f_multivol)
  533.             save_name = 0;
  534.  
  535.         if (f >= 0)
  536.             (void)close(f);
  537.  
  538.         break;
  539.  
  540.         /*
  541.          * File shrunk or gave error, pad out tape to match
  542.          * the size we specified in the header.
  543.          */
  544.     padit:
  545.         while(sizeleft>0) {
  546.             save_sizeleft=sizeleft;
  547.             start=findrec();
  548.             bzero(start->charptr,RECORDSIZE);
  549.             userec(start);
  550.             sizeleft-=RECORDSIZE;
  551.         }
  552.         if(f_multivol)
  553.             save_name=0;
  554.         if(f>=0)
  555.             (void)close(f);
  556.         break;
  557. /*        abort(); */
  558.     }
  559.  
  560. #ifdef S_IFLNK
  561.     case S_IFLNK:            /* Symbolic link */
  562.     {
  563.         int size;
  564.         char linknamebuf[MAXPATHLEN+1]; /* +1 for null */
  565.  
  566.         hstat.st_size = 0;        /* Force 0 size on symlink */
  567.         header = start_header(p, &hstat);
  568.         if (header == NULL)
  569.             goto badfile;
  570.         size = readlink(p, linknamebuf, NAMSIZ);
  571.         if (size < 0)
  572.             goto badperror;
  573.         linknamebuf[size] = '\0';
  574.         header->header.linkflag = LF_SYMLINK;
  575.         /* 
  576.          * BSD tar requires that the link name have a trailing 
  577.          * null.  See the comments in start_header.
  578.          */
  579.         if (size < NAMSIZ) {
  580.             strcpy(header->header.linkname, linknamebuf);
  581.             finish_header(header);    /* Nothing more to do to it */
  582.         } else if (!f_long_names) {
  583.             msg("symbolic link %s too long\n",p);
  584.             break;
  585.         } else {
  586.             size = readlink(p, linknamebuf, MAXPATHLEN);
  587.             linknamebuf[size] = '\0';
  588.             header->header.isextended |= XH_LINKNAME;
  589.             strcpy(header->header.linkname,
  590.                    "LINK_TOO_LONG--CHECK_EXTENDED_HEADER");
  591.             finish_header(header);
  592.             copy_long_name(linknamebuf, XH_LINKNAME);
  593.         }
  594.     }
  595.         break;
  596. #endif
  597. #ifdef S_IFRLNK
  598.     case S_IFRLNK:            /* Remote link */
  599.     {
  600.         int size;
  601.         char linknamebuf[MAXPATHLEN+1]; /* +1 for null */
  602.  
  603.         hstat.st_size = 0;        /* Force 0 size on symlink */
  604.         header = start_header(p, &hstat);
  605.         if (header == NULL)
  606.             goto badfile;
  607.         size = readlink(p,linknamebuf, NAMSIZ+1);
  608.         if (size < 0)
  609.             goto badperror;
  610.         linknamebuf[size] = '\0';
  611.         header->header.linkflag = LF_RMTLINK;
  612.         /* 
  613.          * BSD tar requires that the link name have a trailing 
  614.          * null.  See the comments in start_header.
  615.          */
  616.         if (size < NAMSIZ) {
  617.             strcpy(header->header.linkname, linknamebuf);
  618.             finish_header(header);    /* Nothing more to do to it */
  619.         } else if (!f_long_names) {
  620.             msg("%s: remote link too long\n", p);
  621.             break;
  622.         } else {
  623.             size = readlink(p, linknamebuf, MAXPATHLEN);
  624.             linknamebuf[size] = '\0';
  625.             header->header.isextended |= XH_LINKNAME;
  626.             strcpy(header->header.linkname,
  627.                    "LINK_TOO_LONG--CHECK_EXTENDED_HEADER");
  628.             finish_header(header);
  629.             copy_long_name(linknamebuf, XH_LINKNAME);
  630.         }
  631.     }
  632.         break;
  633. #endif
  634.  
  635. #ifdef S_IFPDEV                         /* Psuedo device */
  636.     case S_IFPDEV:
  637.         hstat.st_size = 0;
  638.         header = start_header(p, &hstat);
  639.         if (header == NULL) goto badfile;
  640.         header->header.linkflag = LF_PSEUDODEV;
  641.         finish_header(header);
  642.         break;
  643. #endif
  644.  
  645.     case S_IFDIR:            /* Directory */
  646.         {
  647.         register DIR *dirp;
  648.         register struct direct *d;
  649. #ifdef ALLOW_LONG_NAMES        
  650.         char namebuf[MAXPATHLEN+2];
  651. #else        
  652.         char namebuf[NAMSIZ+2];
  653. #endif        
  654.         register int len;
  655.         int our_device = hstat.st_dev;
  656.  
  657.         /* Build new prototype name */
  658.         strncpy(namebuf, p, sizeof (namebuf));
  659.         len = strlen(namebuf);
  660.         while (len >= 1 && '/' == namebuf[len-1]) 
  661.             len--;            /* Delete trailing slashes */
  662.         namebuf[len++] = '/';        /* Now add exactly one back */
  663.         namebuf[len] = '\0';        /* Make sure null-terminated */
  664.  
  665.         /*
  666.          * Output directory header record with permissions
  667.          * FIXME, do this AFTER files, to avoid R/O dir problems?
  668.          * If old archive format, don't write record at all.
  669.          */
  670.         if (!f_oldarch) {
  671.             hstat.st_size = 0;    /* Force 0 size on dir */
  672.             /*
  673.              * If people could really read standard archives,
  674.              * this should be:        (FIXME)
  675.             header = start_header(f_standard? p: namebuf, &hstat);
  676.              * but since they'd interpret LF_DIR records as
  677.              * regular files, we'd better put the / on the name.
  678.              */
  679.             header = start_header(namebuf, &hstat);
  680.             if (header == NULL)
  681.                 goto badfile;    /* eg name too long */
  682.  
  683.             if (f_gnudump)
  684.                 header->header.linkflag = LF_DUMPDIR;
  685.             else if (f_standard)
  686.                 header->header.linkflag = LF_DIR;
  687.  
  688.             /* If we're gnudumping, we aren't done yet so don't close it. */
  689.             if(!f_gnudump)
  690.                 finish_header(header);    /* Done with directory header */
  691.         }
  692.  
  693.         /* Hack to remove "./" from the front of all the file names */
  694.         if (len == 2 && namebuf[0] == '.' && namebuf[1]=='/') {
  695.             len = 0;
  696.         }
  697.  
  698.         if(f_gnudump) {
  699.             int sizeleft;
  700.             int totsize;
  701.             int bufsize;
  702.             union record *start;
  703.             int count;
  704.             char *buf,*p_buf;
  705.  
  706.             buf=gnu_list_name->dir_contents; /* FOO */
  707.             totsize=0;
  708.             for(p_buf=buf;*p_buf;) {
  709.                 int tmp;
  710.  
  711.                 tmp=strlen(p_buf)+1;
  712.                 totsize+=tmp;
  713.                 p_buf+=tmp;
  714.             }
  715.             totsize++;
  716.             to_oct((long)totsize,1+12,header->header.size);
  717.             finish_header(header);
  718.             p_buf=buf;
  719.             sizeleft=totsize;
  720.             while(sizeleft>0) {
  721.                 if(f_multivol) {
  722.                     save_name=p;
  723.                     save_sizeleft=sizeleft;
  724.                     save_totsize=totsize;
  725.                 }
  726.                 start=findrec();
  727.                 bufsize=endofrecs()->charptr - start->charptr;
  728.                 if(sizeleft<bufsize) {
  729.                     bufsize=sizeleft;
  730.                     count=bufsize%RECORDSIZE;
  731.                     if(count)
  732.                         bzero(start->charptr+sizeleft,RECORDSIZE-count);
  733.                 }
  734.                 bcopy(p_buf,start->charptr,bufsize);
  735.                 sizeleft-=bufsize;
  736.                 p_buf+=bufsize;
  737.                 userec(start+(bufsize-1)/RECORDSIZE);
  738.             }
  739.             if(f_multivol)
  740.                 save_name = 0;
  741.             break;
  742.         }
  743.  
  744.         /* Now output all the files in the directory */
  745. #ifdef ALLOW_NO_RECURSE
  746.         if (f_no_recurse) {
  747.             break;        /* Unless the cmdline said not to */
  748.         }
  749. #endif        
  750.         errno = 0;
  751.         dirp = opendir(p);
  752.         if (!dirp) {
  753.             if (errno) {
  754.                 msg_perror ("can't open directory %s",p);
  755.             } else {
  756.                 msg("error opening directory %s",
  757.                     p);
  758.             }
  759.             break;
  760.         }
  761.  
  762.         /* Should speed this up by cd-ing into the dir, FIXME */
  763.         while (NULL != (d=readdir(dirp))) {
  764.             /* Skip . and .. */
  765.             if(is_dot_or_dotdot(d->d_name))
  766.                 continue;
  767. #ifdef ALLOW_LONG_NAMES
  768.             if (DP_NAMELEN(d) + len >= MAXPATHLEN) {
  769. #else                
  770.             if (DP_NAMELEN(d) + len >= NAMSIZ) {
  771. #endif                
  772.                 msg("file name %s%s too long\n", 
  773.                     namebuf, d->d_name);
  774.                 continue;
  775.             }
  776.             strcpy(namebuf+len, d->d_name);
  777.             if(f_exclude && check_exclude(namebuf))
  778.                 continue;
  779.             dump_file(namebuf, our_device);
  780.         }
  781.  
  782.         closedir(dirp);
  783.     }
  784.         break;
  785.  
  786. #ifdef S_IFCHR
  787.     case S_IFCHR:            /* Character special file */
  788.         type = LF_CHR;
  789.         goto easy;
  790. #endif
  791.  
  792. #ifdef S_IFBLK
  793.     case S_IFBLK:            /* Block     special file */
  794.         type = LF_BLK;
  795.         goto easy;
  796. #endif
  797.  
  798. #if defined (sprite) && defined (S_IFSOCK)
  799.     case S_IFSOCK:
  800.         /*
  801.          * Fall through and do a named pipe.  The Sprite compatible
  802.          * stat routine maps Sprite named pipes to S_IFSOCK.
  803.          */
  804. #endif
  805. #ifdef S_IFIFO
  806.     case S_IFIFO:            /* Fifo      special file */
  807.  
  808.         type = LF_FIFO;
  809. #endif
  810.  
  811.     easy:
  812.         if (!f_standard) goto unknown;
  813.  
  814.         hstat.st_size = 0;        /* Force 0 size */
  815.         header = start_header(p, &hstat);
  816.         if (header == NULL) goto badfile;    /* eg name too long */
  817.  
  818.         header->header.linkflag = type;
  819.         if (type != LF_FIFO) {
  820.             to_oct((long) major(hstat.st_rdev), 8,
  821.                 header->header.devmajor);
  822.             to_oct((long) minor(hstat.st_rdev), 8,
  823.                 header->header.devminor);
  824.         }
  825.  
  826.         finish_header(header);
  827.         break;
  828.  
  829.     default:
  830.     unknown:
  831.         msg("%s: Unknown file type; file ignored.\n", p);
  832.         break;
  833.     }
  834. }
  835.  
  836. int
  837. finish_sparse_file(fd, sizeleft, fullsize, name)
  838.     int    fd;
  839.     long     *sizeleft,
  840.         fullsize;
  841.     char    *name;
  842. {
  843.     union record    *start;
  844.     char        tempbuf[RECORDSIZE];
  845.     int        bufsize,
  846.             sparse_ind = 0,
  847.             count;
  848.     long        pos;
  849.  
  850.  
  851.  
  852.     while (*sizeleft > 0) {
  853.         start = findrec();
  854.         bzero(start->charptr, RECORDSIZE);
  855.         bufsize = sparsearray[sparse_ind].numbytes;
  856.         if (!bufsize) {  /* we blew it, maybe */
  857.                 fprintf(stderr, "Wrote %ld of %ld bytes to file %s\n",
  858.                        fullsize - *sizeleft, fullsize, name);
  859.             break;
  860.         }
  861.         pos = lseek(fd, sparsearray[sparse_ind++].offset, 0);
  862.         /* 
  863.          * If the number of bytes to be written here exceeds
  864.          * the size of the temporary buffer, do it in steps.
  865.          */
  866.         while (bufsize > RECORDSIZE) {
  867. /*            if (amt_read) {
  868.                 count = read(fd, start->charptr+amt_read, RECORDSIZE-amt_read);
  869.                 bufsize -= RECORDSIZE - amt_read;
  870.                 amt_read = 0;
  871.                 userec(start);
  872.                 start = findrec();
  873.                 bzero(start->charptr, RECORDSIZE);
  874.             }*/
  875.             /* store the data */
  876.             count = read(fd, start->charptr, RECORDSIZE);
  877.             if (count < 0)     {
  878.                 msg_perror("read error at byte %ld, reading %d bytes, in file %s", 
  879.                         fullsize - *sizeleft, bufsize, name);
  880.                 return 1;
  881.             }            
  882.             bufsize -= count;
  883.             *sizeleft -= count;
  884.             userec(start);
  885.             start = findrec();
  886.             bzero(start->charptr, RECORDSIZE);
  887.         }
  888.  
  889.  
  890.         clear_buffer(tempbuf);
  891.         count = read(fd, tempbuf, bufsize);
  892.         bcopy(tempbuf, start->charptr, RECORDSIZE);
  893.         if (count < 0)     {
  894.             msg_perror("read error at byte %ld, reading %d bytes, in file %s", 
  895.                     fullsize - *sizeleft, bufsize, name);
  896.             return 1;
  897.         }
  898. /*        if (amt_read >= RECORDSIZE) {
  899.             amt_read = 0;
  900.             userec(start+(count-1)/RECORDSIZE);
  901.             if (count != bufsize) {
  902.                 msg("file %s shrunk by %d bytes, padding with zeros.\n", name, sizeleft);
  903.                 return 1;
  904.             }
  905.             start = findrec();
  906.         } else 
  907.             amt_read += bufsize;*/
  908.         *sizeleft -= count;
  909.         userec(start);
  910.  
  911.     }
  912. /*    userec(start+(count-1)/RECORDSIZE);*/
  913.     return 0;
  914.  
  915. }
  916.  
  917. init_sparsearray()
  918. {
  919.     register int i;
  920.  
  921.     for (i = 0; i < sp_array_size; i++) {
  922.         sparsearray[i].offset = 0;
  923.         sparsearray[i].numbytes = 0;
  924.     }
  925. }
  926.  
  927.  
  928.  
  929. /*
  930.  * Okay, we've got a sparse file on our hands -- now, what we need to do is
  931.  * make a pass through the file and carefully note where any data is, i.e.,
  932.  * we want to find how far into the file each instance of data is, and how
  933.  * many bytes are there.  We store this information in the sparsearray,
  934.  * which will later be translated into header information.  For now, we use
  935.  * the sparsearray as convenient storage.
  936.  *
  937.  * As a side note, this routine is a mess.  If I could have found a cleaner
  938.  * way to do it, I would have.  If anyone wants to find a nicer way to do
  939.  * this, feel free.
  940.  */
  941. int
  942. deal_with_sparse(name, header, nulls_at_end)
  943.     char        *name;
  944.     union record     *header;
  945.  
  946. {
  947.     long    numbytes = 0;
  948.     long    offset = 0;
  949.     int    fd;
  950.     int    start,
  951.         end;
  952.     int    end_nulls = 0;
  953.     int    sparse_ind = 0,
  954.         cc;
  955.     char    buf[RECORDSIZE];
  956.     int     amidst_data = 0;
  957.  
  958.     header->header.isextended = 0;
  959.     /* 
  960.      * Can't open the file -- this problem will be caught later on,
  961.      * so just return.
  962.      */
  963.     if ((fd = open(name, O_RDONLY)) < 0)
  964.         return;
  965.  
  966.     sp_array_size = 10;
  967.     /* 
  968.      * Make room for our scratch space -- initially is 10 elts long
  969.      */
  970.     sparsearray = (struct sp_array *) malloc(sp_array_size * sizeof(struct sp_array));
  971.  
  972.     init_sparsearray();
  973.     clear_buffer(buf);
  974.  
  975.     while ((cc = read(fd, buf, sizeof buf)) != 0) {
  976.  
  977.         if (sparse_ind > sp_array_size-1) {
  978.  
  979.         /*
  980.          * realloc the scratch area, since we've run out of room --
  981.          */
  982.             sparsearray = (struct sp_array *) 
  983.                     realloc(sparsearray,
  984.                         2 * sp_array_size * (sizeof(struct sp_array)));
  985.             sp_array_size *= 2;
  986.         }
  987.         if (cc == sizeof buf) {
  988.             if (zero_record(buf)) {
  989.                 if (amidst_data) {
  990.                     sparsearray[sparse_ind++].numbytes
  991.                         = numbytes;
  992.                     amidst_data = 0;
  993.                     numbytes = 0;
  994.                 }
  995.                 offset += cc;
  996.             } else {  /* !zero_record(buf) */
  997.                 if (!amidst_data) {
  998.                         amidst_data = 1;
  999.                     where_is_data(&start, &end, buf);
  1000.                     numbytes += end - start;
  1001.                     offset += start;
  1002.                     sparsearray[sparse_ind].offset = offset;
  1003.                 } else
  1004.                     numbytes += cc;
  1005.                 offset += cc;
  1006.             }
  1007.         } else if (cc < sizeof buf) {
  1008.             if (!zero_record(buf)) {
  1009.                 if (!amidst_data) {
  1010.                     amidst_data = 1;
  1011.                     where_is_data(&start, &end, buf);
  1012.                     /* In case there are nulls at the 
  1013.                        end that we need to remember */
  1014.                     if (end < cc)
  1015.                         end = cc;
  1016.                     numbytes += start - end;
  1017.                     offset += start;
  1018. /*                    end_nulls = RECORDSIZE - end;*/
  1019.                 } else {
  1020.                     numbytes += cc;
  1021. /*                    end_nulls = RECORDSIZE - end;*/
  1022.                 }
  1023.                 sparsearray[sparse_ind].numbytes = numbytes;
  1024.             } /* else
  1025.                 end_nulls = cc;*/
  1026.         }
  1027.         clear_buffer(buf);
  1028.     }
  1029.     if (numbytes)
  1030.             sparsearray[sparse_ind].numbytes = numbytes;
  1031.     close(fd);
  1032. /*    printf("%d\n", end_nulls);
  1033.     *nulls_at_end = end_nulls;*/
  1034.  
  1035.     return sparse_ind;
  1036. }
  1037.  
  1038. /* 
  1039.  * Just zeroes out the buffer so we don't confuse ourselves with leftover
  1040.  * data.
  1041.  */
  1042. clear_buffer(buf)
  1043.     char    *buf;
  1044. {
  1045.     register int     i;
  1046.  
  1047.     for (i = 0; i < RECORDSIZE; i++)
  1048.         buf[i] = '\0';
  1049. }
  1050.  
  1051. /* 
  1052.  * JK - 
  1053.  * This routine takes a character array, and tells where within that array
  1054.  * the data can be found.  It skips over any zeros, and sets the first
  1055.  * non-zero point in the array to be the "start", and continues until it
  1056.  * finds non-data again, which is marked as the "end."  This routine is 
  1057.  * mainly for 1) seeing how far into a file we must lseek to data, given
  1058.  * that we have a sparse file, and 2) determining the "real size" of the
  1059.  * file, i.e., the number of bytes in the sparse file that are data, as
  1060.  * opposed to the zeros we are trying to skip.
  1061.  */
  1062. where_is_data(from, to, buffer)
  1063.     int    *from,
  1064.         *to;
  1065.     char    *buffer;
  1066. {
  1067.     register int    i = 0;
  1068.     register int    save_to = *to;
  1069.     int    amidst_data = 0;
  1070.  
  1071.  
  1072.     while (!buffer[i])
  1073.         i++;
  1074.     *from = i;
  1075.  
  1076.     if (*from < 16)    /* don't bother */
  1077.         *from = 0;
  1078.     /* keep going to make sure there isn't more real
  1079.        data in this record */
  1080.     while (i < RECORDSIZE) {
  1081.         if (!buffer[i]) {
  1082.             if (amidst_data) {
  1083.                 save_to = i;
  1084.                 amidst_data = 0;
  1085.             }
  1086.             i++;
  1087.         }
  1088.         else if (buffer[i]) {
  1089.             if (!amidst_data)
  1090.                 amidst_data = 1;
  1091.             i++;
  1092.         }
  1093.     }
  1094.     if (i == RECORDSIZE)
  1095.         *to = i;
  1096.     else
  1097.         *to = save_to;
  1098.  
  1099. }
  1100.  
  1101. /*
  1102.  * Takes a recordful of data and basically cruises through it to see if
  1103.  * it's made *entirely* of zeros, returning a 0 the instant it finds
  1104.  * something that is a non-zero, i.e., useful data.
  1105.  */
  1106. zero_record(buffer)
  1107.     char    *buffer;
  1108. {
  1109.     register int    i;
  1110.  
  1111.     for (i = 0; i < RECORDSIZE; i++)
  1112.         if (buffer[i] != '\000')
  1113.             return 0;
  1114.     return 1;
  1115. }
  1116.  
  1117. find_new_file_size(filesize, highest_index)
  1118.     int    *filesize;
  1119.     int    highest_index;
  1120. {
  1121.     register int     i;
  1122.  
  1123.     *filesize = 0;
  1124.     for (i = 0; sparsearray[i].numbytes && i <= highest_index; i++)
  1125.         *filesize += sparsearray[i].numbytes;
  1126. }
  1127.  
  1128. /*
  1129.  * Make a header block for the file  name  whose stat info is  st .
  1130.  * Return header pointer for success, NULL if the name is too long.
  1131.  */
  1132. union record *
  1133. start_header(name, st)
  1134.     char    *name;
  1135.     register struct stat *st;
  1136. {
  1137.     register union record *header;
  1138.  
  1139.     header = (union record *) findrec();
  1140.     bzero(header->charptr, sizeof(*header)); /* XXX speed up */
  1141.  
  1142.     header->header.hdr_magic = HDR_MAGIC;
  1143.  
  1144.     /*
  1145.      * Check the file name and put it in the record.
  1146.      */
  1147. #ifdef MSDOS
  1148.     if(name[1]==':') {
  1149.         static int warned_once = 0;
  1150.         name+=2;
  1151.         if(!warned_once++) {
  1152.             msg("Removing drive spec from names in the archive");
  1153.         }
  1154.     }
  1155. #endif
  1156.     while (!f_absolute_paths && '/' == *name) {
  1157.         static int warned_once = 0;
  1158.  
  1159.         name++;                /* Force relative path */
  1160.         if (!warned_once++) {
  1161.             msg("Removing leading / from absolute path names in the archive.");
  1162.         }
  1163.     }
  1164.     /* 
  1165.      * Posix lets the name take up all NAMSIZ characters, but BSD tar 
  1166.      * requires a trailing null.  We can't pretend to be Posix 
  1167.      * compliant for other reasons, so let's at least try to be
  1168.      * compatible with BSD.
  1169.      */
  1170.     if (strlen(name) < NAMSIZ) {
  1171.         strcpy(header->header.name, name);
  1172.     } else if (!f_long_names) {
  1173.         msg("%s: name too long\n", name);
  1174.         return NULL;
  1175.     } else {
  1176.         int size;
  1177.         static long unique;
  1178.         
  1179.         header->header.isextended |= XH_FILENAME;
  1180.         size = strlen(name);
  1181.         if (size >= MAXPATHLEN) {
  1182.             msg("%s: file name exceeds MAXPATHLEN\n", name);
  1183.             return NULL;
  1184.         }
  1185.         sprintf(header->header.name, "/tmp/TAR.NAME_TOO_LONG.%08ld",
  1186.             ++unique);
  1187.         strcpy(longname, name);
  1188.     }
  1189.  
  1190.     to_oct((long) (st->st_mode & ~S_IFMT),
  1191.                     8,  header->header.mode);
  1192.     to_oct((long) st->st_uid,    8,  header->header.uid);
  1193.     to_oct((long) st->st_gid,    8,  header->header.gid);
  1194.     to_oct((long) st->st_size,    1+12, header->header.size);
  1195.     to_oct((long) st->st_mtime,    1+12, header->header.mtime);
  1196.     /* header->header.linkflag is left as null */
  1197.     if(f_gnudump) {
  1198.         to_oct((long) st->st_atime, 1+12, header->header.atime);
  1199.         to_oct((long) st->st_ctime, 1+12, header->header.ctime);
  1200.     }
  1201.  
  1202. #ifndef NONAMES
  1203.     /* Fill in new Unix Standard fields if desired. */
  1204.     if (f_standard) {
  1205.         header->header.linkflag = LF_NORMAL;    /* New default */
  1206.         strcpy(header->header.magic, TMAGIC);    /* Mark as Unix Std */
  1207.         finduname(header->header.uname, st->st_uid);
  1208.         findgname(header->header.gname, st->st_gid);
  1209.     }
  1210. #endif
  1211.     return header;
  1212. }
  1213.  
  1214. /* 
  1215.  * Finish off a filled-in header block and write it out.
  1216.  * We also print the file name and/or full info if verbose is on.
  1217.  * 
  1218.  * Note: this code should be able to handle Posix names (no terminating 
  1219.  * null in the header).
  1220.  */
  1221. void
  1222. finish_header(header)
  1223.     register union record *header;
  1224. {
  1225.     register int    i, sum;
  1226.     register char    *p;
  1227.     void bcopy();
  1228.     char shortname[NAMSIZ+1]; /* copy from header; +1 for null */
  1229.  
  1230.     bcopy(CHKBLANKS, header->header.chksum, sizeof(header->header.chksum));
  1231.  
  1232.     sum = 0;
  1233.     p = header->charptr;
  1234.     for (i = sizeof(*header); --i >= 0; ) {
  1235.         /*
  1236.          * We can't use unsigned char here because of old compilers,
  1237.          * e.g. V7.
  1238.          */
  1239.         sum += 0xFF & *p++;
  1240.     }
  1241.  
  1242.     /*
  1243.      * Fill in the checksum field.  It's formatted differently
  1244.      * from the other fields:  it has [6] digits, a null, then a
  1245.      * space -- rather than digits, a space, then a null.
  1246.      * We use to_oct then write the null in over to_oct's space.
  1247.      * The final space is already there, from checksumming, and
  1248.      * to_oct doesn't modify it.
  1249.      *
  1250.      * This is a fast way to do:
  1251.      * (void) sprintf(header->header.chksum, "%6o", sum);
  1252.      */
  1253.     to_oct((long) sum,    8,  header->header.chksum);
  1254.     header->header.chksum[6] = '\0';    /* Zap the space */
  1255.  
  1256.     userec(header);
  1257.  
  1258.     if (f_verbose) {
  1259.         /* These globals are parameters to print_header, sigh */
  1260.         head = header;
  1261.         /* hstat is already set up */
  1262.         head_standard = f_standard;
  1263.         if (current_filename != NULL) {
  1264.             free(current_filename);
  1265.         }
  1266.         if (header->header.isextended & XH_FILENAME) {
  1267.             current_filename = strdup(longname);
  1268.         } else {
  1269.             strncpy(shortname, head->header.name, NAMSIZ);
  1270.             shortname[NAMSIZ] = '\0';
  1271.             current_filename = strdup(shortname);
  1272.         }
  1273.         /* 
  1274.          * XXX We don't have the link name, but that's okay as long 
  1275.          * as print_header doesn't need it, which is true if 
  1276.          * f_verbose == 1.
  1277.          */
  1278.         assert(f_verbose == 1);
  1279.         print_header();
  1280.     }
  1281.     if (!f_long_names) {
  1282.         assert((header->header.isextended &
  1283.             (XH_FILENAME|XH_LINKNAME)) == 0);
  1284.     } else {
  1285.         if (header->header.isextended & XH_FILENAME) {
  1286.             copy_long_name(longname, XH_FILENAME);
  1287.         }
  1288.     }
  1289.     return;
  1290. }
  1291.  
  1292. /*
  1293.  * Quick and dirty octal conversion.
  1294.  * Converts long "value" into a "digs"-digit field at "where",
  1295.  * including a trailing space and room for a null.  "digs"==3 means
  1296.  * 1 digit, a space, and room for a null.
  1297.  *
  1298.  * We assume the trailing null is already there and don't fill it in.
  1299.  * This fact is used by start_header and finish_header, so don't change it!
  1300.  *
  1301.  * This should be equivalent to:
  1302.  *    (void) sprintf(where, "%*lo ", digs-2, value);
  1303.  * except that sprintf fills in the trailing null and we don't.
  1304.  */
  1305. void
  1306. to_oct(value, digs, where)
  1307.     register long    value;
  1308.     register int    digs;
  1309.     register char    *where;
  1310. {
  1311.  
  1312.     --digs;                /* Trailing null slot is left alone */
  1313.     where[--digs] = ' ';        /* Put in the space, though */
  1314.  
  1315.     /* Produce the digits -- at least one */
  1316.     do {
  1317.         where[--digs] = '0' + (char)(value & 7); /* one octal digit */
  1318.         value >>= 3;
  1319.     } while (digs > 0 && value != 0);
  1320.  
  1321.     /* Leading spaces, if necessary */
  1322.     while (digs > 0)
  1323.         where[--digs] = ' ';
  1324.  
  1325. }
  1326.  
  1327.  
  1328. /*
  1329.  * Write the EOT record(s).
  1330.  * We actually zero at least one record, through the end of the block.
  1331.  * Old tar writes garbage after two zeroed records -- and PDtar used to.
  1332.  */
  1333. write_eot()
  1334. {
  1335.     union record *p;
  1336.     int bufsize;
  1337.     void bzero();
  1338.  
  1339.     p = findrec();
  1340.     bufsize = endofrecs()->charptr - p->charptr;
  1341.     bzero(p->charptr, bufsize);
  1342.     userec(p);
  1343. }
  1344.  
  1345.  
  1346. static int
  1347. copy_long_name(name, type)
  1348.     char *name;
  1349.     int type;
  1350. {
  1351.     int size;
  1352.     union record *exhdr;
  1353.  
  1354.     assert(type == XH_FILENAME || type == XH_LINKNAME);
  1355.     size = strlen(name);
  1356.     assert(size >= NAMSIZ);
  1357.     assert(size <= MAXPATHLEN);
  1358.     for (;;) {
  1359.     assert(strlen(name) == size);
  1360.     exhdr = findrec();
  1361.     if (exhdr == NULL) {
  1362.         return 0;        /* XXX nobody actually looks at this number */
  1363.     }
  1364.  
  1365.     /* 
  1366.      * Make sure that the string will be null-terminated
  1367.      */
  1368.     bzero(exhdr, sizeof(exhdr));
  1369.  
  1370.     exhdr->ext_hdr.xh_type = type;
  1371.     exhdr->ext_hdr.xh_magic = XH_MAGIC;
  1372.     strncpy(exhdr->ext_hdr.xh_namebuf, name,
  1373.         sizeof(exhdr->ext_hdr.xh_namebuf));
  1374.     if (size >= sizeof(exhdr->ext_hdr.xh_namebuf)) {
  1375.         size -= sizeof(exhdr->ext_hdr.xh_namebuf);
  1376.         name += sizeof(exhdr->ext_hdr.xh_namebuf);
  1377.         exhdr->ext_hdr.xh_isextended |= type;
  1378.         userec(exhdr);
  1379.         continue;
  1380.     } else {
  1381.         exhdr->ext_hdr.xh_isextended = 0;
  1382.         userec(exhdr);
  1383.         return 1;
  1384.     }
  1385.     }
  1386. }
  1387.  
  1388.